/*
 * Copyright 2011 OpenWAF.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.openwaf.client.ui.dialog;

import com.openwaf.client.core.Window;
import com.openwaf.client.dom.DivElement;
import com.openwaf.client.dom.Element;
import com.openwaf.client.dom.Style;
import com.openwaf.client.event.HandlerRegistration;
import com.openwaf.client.event.KeyCodes;
import com.openwaf.client.event.dom.ClickEvent;
import com.openwaf.client.event.dom.ClickHandler;
import com.openwaf.client.event.dom.KeyDownEvent;
import com.openwaf.client.event.dom.KeyDownHandler;
import com.openwaf.client.event.dom.MouseDownEvent;
import com.openwaf.client.event.dom.MouseDownHandler;
import com.openwaf.client.event.dom.MouseMoveEvent;
import com.openwaf.client.event.dom.MouseMoveHandler;
import com.openwaf.client.event.dom.MouseUpEvent;
import com.openwaf.client.event.dom.MouseUpHandler;
import com.openwaf.client.ui.UIControl;

public class DialogBox extends UIControl {

    private static class LayerScreen extends UIControl {

        LayerScreen() {
            Element elm = Window.getDocument().createElement(DivElement.TAG);
            elm.setCssClassName("waf-dialog-layer-screen");
            setElement(elm);
            elm.addClickHandler(new ClickHandler() {

                public void onClick(ClickEvent event) {
                    event.getNativeEvent().stopPropagation();
                }
            });
        }

        void setZIndex(int index) {
            getElement().getStyle().setZIndex(index);
        }
    }
    private static int zindex_counter = 1000;
    private LayerScreen layer;
    private DialogBoxBase base;
    private boolean dialog_shown;
    private Element mycontentelement;
    private boolean titleMouseDown;
    private HandlerRegistration mouseUpHandler;
    private HandlerRegistration mouseMoveHandler;
    private int dragStartX;
    private int dragStartY;
    private int startLeft;
    private int startTop;
    private DialogTaskHandler taskHandler;

    public DialogTaskHandler getTaskHandler(){
        return taskHandler;
    }
    public DialogBox() {
        super();
        base = new DialogBoxBase();
        /*
         * Here the main logic why dialog works i.e switch the root element
         */
        mycontentelement = getElement();
        setElement(base.getElement());
        if (mycontentelement != null) {
            base.divContent.appendChild(mycontentelement);
            base.spanClose.addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent event) {
                    onClose();
                }
            });
        }
        base.divTitle.addMouseDownHandler(new MouseDownHandler() {

            public void onMouseDown(MouseDownEvent event) {
                onDragStart(event);
                event.getNativeEvent().preventDefault();
                event.getNativeEvent().stopPropagation();
            }
        });
        this.addKeyDownHandler(new KeyDownHandler() {

            public void onKeyDown(KeyDownEvent event) {
                if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ESCAPE) {
                    onClose();
                }
            }
        });
    }

    private void onDragStart(MouseDownEvent mousedown) {
        titleMouseDown = true;
        mouseUpHandler = Window.getDocument().addMouseUpHandler(new MouseUpHandler() {

            public void onMouseUp(MouseUpEvent event) {
                mouseUpHandler.removeHandler();
                mouseMoveHandler.removeHandler();
                titleMouseDown = false;
            }
        });
        dragStartX = mousedown.getScreenX();
        dragStartY = mousedown.getScreenY();
        startLeft = getElement().getOffsetLeft();
        startTop = getElement().getOffsetTop();
        mouseMoveHandler = Window.getDocument().addMouseMoveHandler(new MouseMoveHandler() {

            public void onMouseMove(MouseMoveEvent event) {
                Style s = getElement().getStyle();
                s.setLeft("" + (startLeft + (event.getScreenX() - dragStartX)) + "px");
                s.setTop("" + (startTop + (event.getScreenY() - dragStartY)) + "px");
                event.getNativeEvent().preventDefault();
                event.getNativeEvent().stopPropagation();
            }
        });
    }

    private int getIntValue(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }
        if (s.endsWith("px")) {
            s = s.substring(0, s.length() - 2);
        }
        try {
            return Integer.parseInt(s);
        } catch (Exception e) {
        }
        return 0;
    }

    @Override
    public String getTitle() {
        return base.spanTitleText.getInnerHTML();
    }

    @Override
    public void setTitle(String title) {
        base.spanTitleText.setInnerHTML(title);
    }

    public Element getContentElement() {
        return mycontentelement;
    }

    public void show(DialogTaskHandler handler) {
        taskHandler = handler;
        _show();
    }

    public void show() {
        taskHandler = null;
        _show();
    }

    private void _show() {
        if (dialog_shown) {
            return;
        }
        if (layer == null) {
            layer = new LayerScreen();
        }
        zindex_counter++;
        Element body = Window.getDocument().getBodyElement();
        body.appendChild(layer.getElement());
        layer.setZIndex(zindex_counter);
        body.appendChild(getElement());
        zindex_counter++;
        getElement().getStyle().setZIndex(zindex_counter);
        dialog_shown = true;
        layer.getElement().getStyle().setHeight("100%");
        adjustWindowPosition();
        getElement().focus();
    }

    protected void adjustWindowPosition() {
        int width = layer.getOffsetWidth();
        int height = layer.getOffsetHeight();
        int mywidth = getOffsetWidth();
        int myheight = getOffsetHeight();
        int left = (width / 2) - (mywidth / 2);
        int top = (height / 2) - (myheight / 2);
        if (left < 0) {
            left = 0;
        }
        if (top < 0) {
            top = 0;
        }
        getElement().getStyle().setLeft("" + left + "px");
        getElement().getStyle().setTop("" + top + "px");
    }

    protected void hide() {
        if (dialog_shown) {
            Element body = Window.getDocument().getBodyElement();
            body.removeChild(getElement());
            body.removeChild(layer.getElement());
            zindex_counter--;
            zindex_counter--;
            dialog_shown = false;
        }
    }

    public void close() {
        hide();
    }

    public void onClose() {
        if (taskHandler == null) {
            hide();
        } else {
            taskHandler.onAbort(this);
            hide();            
        }
    }
}
